package com.kust.smarthome.web.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.kust.smarthome.web.model.*;
import com.kust.smarthome.web.service.IDetectorService;
import com.kust.smarthome.web.service.IDeviceStateService;
import com.kust.smarthome.web.service.INoticeService;
import com.kust.smarthome.web.service.IUserService;
import com.kust.smarthome.web.vo.DeviceVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.security.Principal;
import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author iAuzre
 * @since 2021-06-28
 */
@RestController
@RequestMapping("/detector")
@Api(value = "烟雾报警器相关操作", tags = {"device-tag"})
public class DetectorController {

    @Resource
    private IDetectorService detectorService;

    @Resource
    private IDeviceStateService deviceStateService;

    @Resource
    private IUserService userService;

    @GetMapping("")
    @ApiOperation(value = "获取烟雾报警器信息", notes = "根据用户信息获取烟雾报警器List")
    public List<Detector> list(Principal principal) {
        User u = userService.getByUsername(principal.getName());
        return detectorService.getByUserId(u.getId());
    }

    @GetMapping("/getById")
    @ApiOperation(value = "getById", notes = "通过id获取对应设备")
    public Detector getById(Integer id) {
        return detectorService.getById(id);
    }

    /**
     * 客户端请求一次开关烟雾报警器,传给后端id,若该id对应的窗帘的状态为1(开)则将状态变为0,反之变为1
     * 同时,在状态表中插入对应状态
     * @param id curtain.getId()
     * @return 返回所有的烟雾报警器属性,前端js代码成功收到响应之后将vue中的数据重新绑定即可
     */
    @GetMapping("/update")
    @Transactional
    @ApiOperation(value = "开关烟雾报警器", notes = "根据id以及用户信息关闭报警器")
    public List<Detector> updateById(Principal principal, Integer id) {
        Detector detector = detectorService.getById(id);

        detectorService.updateById(detector);
        DeviceState deviceState = new DeviceState()
                .setDeviceId(id)
                .setTypeId(4)
                .setIsUpdate(0);
        //更改状态通知
        QueryWrapper<DeviceState> queryD = new QueryWrapper<>();
        queryD.eq("device_id",id);
        queryD.eq("type_id",4);
        deviceStateService.update(deviceState,queryD);

        User u = userService.getByUsername(principal.getName());
        return detectorService.getByUserId(u.getId());
    }

    /**
     * 网页端用户添加窗帘,方法中初始化一个窗帘对象并插入到数据表中
     * 若对窗帘数量有限制,前端可以添加一个判定条件,是否执行异步请求,同时后端也会做一次判定
     * 最大数量先定为3
     * @return 返回插入之后的窗帘列表
     */
    @GetMapping("/add")
    @Transactional
    @ApiOperation(value = "添加烟雾报警器", notes = "用户提供烟雾报警器id添加新的烟雾报警器")
    public List<Detector> addCurtain(Principal principal, DeviceVo deviceVo){

        User u = userService.getByUsername(principal.getName());

        List<Detector> list = detectorService.getByUserId(u.getId());

        Detector detector = new Detector();
        LocalDateTime now = LocalDateTime.now();
        if (list.size() < 3) {
            detector.setUrl("")
                    .setId(deviceVo.getId())
                    .setContent("这是一只烟雾报警器")
                    .setState(0)
                    .setCreated(now)
                    .setUserId(u.getId())
                    .setRoomId(deviceVo.getRoomId());
            list.add(detector);
            DeviceState deviceState = new DeviceState()
                    .setDeviceId(deviceVo.getId())
                    .setTypeId(4)
                    .setIsUpdate(0);
            //插入状态变更通知
            deviceStateService.insert(deviceState);
        }

        return list;
    }

    /**
     * 删除一个烟雾报警器对象操作
     * 同时要删除其所对应的状态表
     * @param id 由客户端传入一个id
     * @return 当后端处理完删除操作之后返回当前数据库中的窗帘对象列表
     */
    @GetMapping("/deleteById")
    @Transactional
    @ApiOperation(value = "删除烟雾报警器", notes = "根据id删除烟雾报警器")
    public boolean deleteById(Integer id) {
        Detector detector = detectorService.getById(id);
        detector.setUserId(-1);
        boolean d = detectorService.updateById(detector);
        QueryWrapper<DeviceState> query = new QueryWrapper<>();
        query.eq("device_id",detector.getId());
        query.eq("type_id",4);
        deviceStateService.remove(query);

        return d;
    }

    @Resource
    private INoticeService noticeService;

    /**
     * 报警操作,当室内存在火灾异常,被对应的烟雾报警器检测到
     * 烟雾报警器发送"/detector/warning"请求
     * 插入一条notice数据,默认state为0,在app点击之后state为1,可被app删除
     * @param id 这个id为对应烟雾报警器id
     */
    @GetMapping("/warning")
    @Transactional
    @ApiOperation(value = "警告请求", notes = "烟雾报警器检测出异常之后向服务器发送警告请求")
    public void warningById(Integer id) {

        Detector detector = detectorService.getById(id);

        QueryWrapper<Notice> query = new QueryWrapper<>();
        query.eq("device_id", id);
        Notice n = noticeService.getOne(query);
        if (n != null)
            return;

        Notice notice = new Notice()
                .setUserId(detector.getUserId())
                .setTypeId(4)
                .setDeviceId(id)
                .setContent("有烟雾异常")
                .setCreated(LocalDateTime.now())
                .setState(0);

        noticeService.save(notice);
    }
}
